package com.zusmart.core.bean.support;

import java.util.Set;

import com.zusmart.base.util.Assert;
import com.zusmart.core.bean.BeanDefinition;
import com.zusmart.core.bean.BeanDefinitionResolver;
import com.zusmart.core.bean.BeanInstanceCreator;
import com.zusmart.core.bean.aware.ApplicationContextAware;
import com.zusmart.core.bean.aware.BeanDefinitionAware;
import com.zusmart.core.bean.aware.BeanDefinitionRegistryAware;
import com.zusmart.core.bean.aware.ConfigSourceManagerAware;
import com.zusmart.core.bean.aware.PluginManagerAware;
import com.zusmart.core.bean.cause.BeanDefinitionNotFoundException;
import com.zusmart.core.bean.cause.BeanInstanceCreateException;
import com.zusmart.core.interceptor.InterceptorHandler;
import com.zusmart.core.proxy.ProxyManager;

public abstract class AbstractBeanInstanceCreator implements BeanInstanceCreator {

	private final BeanDefinition beanDefinition;

	protected AbstractBeanInstanceCreator(BeanDefinition beanDefinition) {
		Assert.isNull(beanDefinition, "bean definition must not be null");
		this.beanDefinition = beanDefinition;
	}

	@Override
	public BeanDefinition getBeanDefinition() {
		return this.beanDefinition;
	}

	@Override
	public Object createBeanInstance() throws BeanInstanceCreateException {
		Object beanInstance = this.doCreateBeanInstance();
		if (null == beanInstance) {
			throw new BeanInstanceCreateException();
		}
		if(beanInstance instanceof ApplicationContextAware){
			((ApplicationContextAware) beanInstance).setApplicationContext(this.getBeanDefinition().getBeanDefinitionRegistry().getApplicationContext());
		}
		if (beanInstance instanceof BeanDefinitionRegistryAware) {
			((BeanDefinitionRegistryAware) beanInstance).setBeanDefinitionRegistry(this.getBeanDefinition().getBeanDefinitionRegistry());
		}
		if (beanInstance instanceof BeanDefinitionAware) {
			((BeanDefinitionAware) beanInstance).setBeanDefinition(this.getBeanDefinition());
		}
		if (beanInstance instanceof ConfigSourceManagerAware) {
			((ConfigSourceManagerAware) beanInstance).setConfigSourceManager(this.getBeanDefinition().getBeanDefinitionRegistry().getConfigSourceManager());
		}
		if (beanInstance instanceof PluginManagerAware) {
			((PluginManagerAware) beanInstance).setPluginManager(this.getBeanDefinition().getBeanDefinitionRegistry().getPluginManager());
		}
		return beanInstance;
	}

	protected ProxyManager getProxyManager() {
		return this.getBeanDefinition().getBeanDefinitionRegistry().getProxyManager();
	}

	protected BeanDefinitionResolver getBeanDefinitionResolver() {
		return this.getBeanDefinition().getBeanDefinitionResolver();
	}
	
	protected InterceptorHandler[] searchInterceptorHandlers(Class<?> beanType) throws BeanDefinitionNotFoundException {
		BeanDefinitionResolver beanDefinitionResolver = this.getBeanDefinition().getBeanDefinitionResolver();
		Set<BeanDefinition> beanDefinitions = beanDefinitionResolver.getBeanDefinitionProxy(beanType);
		if (null == beanDefinitions || beanDefinitions.isEmpty()) {
			return new InterceptorHandler[0];
		}
		InterceptorHandler[] interceptorHandlers = new InterceptorHandler[beanDefinitions.size()];
		int index = 0;
		for (BeanDefinition beanDefinition : beanDefinitions) {
			interceptorHandlers[index++] = new InterceptorHandler(beanDefinition);
		}
		return interceptorHandlers;
	}

	protected abstract Object doCreateBeanInstance() throws BeanInstanceCreateException;

}